﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using System.Xml;
using System.Net;

namespace eBay {
    public partial class API {

        public class ShoppingAPI {

            /// <summary>
            /// Gets the search results for FindItems Call
            /// </summary>
            /// <param name="QueryKeywords">Query keywords parameter for the search</param>
            /// <param name="SortOrder">Ascending or Descending sort order.</param>
            /// <param name="MaxEntries">Max results to return. Default: 3</param>
            /// <returns>XmlDocument with search results</returns>
            /// <exception cref="eBay.API.Exceptions.NoQueryKeywordsSetException">No QueryKeywords parameter set</exception>
            /// <exception cref="eBay.API.Exceptions.UnknownException">Unknown Exception with a message included</exception>
            public static FindItemsResponseType FindItems(string QueryKeywords, SortOrderCodeType SortOrder, int MaxEntries) {
                return FindItems(QueryKeywords, SortOrder, MaxEntries, false, "", SimpleItemSortCodeType.BestMatch);
            }

            /// <summary>
            /// Gets the search results for FindItems Call
            /// </summary>
            /// <param name="QueryKeywords">Query keywords parameter for the search</param>
            /// <param name="SortOrder">Ascending or Descending sort order.</param>
            /// <param name="MaxEntries">Max results to return. Default: 3</param>
            /// <param name="HideDuplicateItems">Hide duplicating result items</param>
            /// <param name="PostalCode">Postal code of the country</param>
            /// <param name="ItemSort">Advanced item sort order.</param>
            /// <returns>XmlDocument with search results</returns>
            /// <exception cref="eBay.API.Exceptions.NoQueryKeywordsSetException">No QueryKeywords parameter set</exception>
            /// <exception cref="eBay.API.Exceptions.UnknownException">Unknown Exception with a message included</exception>
            public static FindItemsResponseType FindItems(string QueryKeywords, SortOrderCodeType SortOrder, int MaxEntries, bool HideDuplicateItems, string PostalCode, SimpleItemSortCodeType ItemSort) {
                FindItemsRequestType request = new FindItemsRequestType();
                request.QueryKeywords = QueryKeywords;
                request.SortOrder = SortOrder;
                request.HideDuplicateItems = HideDuplicateItems;
                request.ItemSort = ItemSort;
                request.MaxEntries = MaxEntries;
                request.PostalCode = PostalCode;

                FindItemsResponseType response = (FindItemsResponseType)request.Execute();

                return response;

            }

            public static FindItemsAdvancedResponseType FindItemsAdvanced(Dictionary<string, object> Params) {
                //Load the XML Document to Use for this Request
                XmlDocument xmlDoc = new XmlDocument();

                //Get XML Document from Embedded  Resources
                xmlDoc.Load(Common.Funcs.GetAppPath() + "APICalls\\FindItemsAdvancedRequest.xml");
                XmlNode nd = xmlDoc["FindItemsAdvancedRequest"];

                string QueryKeywords = "";
                string CategoryID = "";
                string ProductID = "";
                string SellerID = "";
                if (Params.ContainsKey("QueryKeywords"))
                    QueryKeywords = Params["QueryKeywords"] + "";
                if (Params.ContainsKey("CategoryID"))
                    CategoryID = Params["CategoryID"] + "";
                if (Params.ContainsKey("ProductID"))
                    ProductID = Params["ProductID"] + "";
                if (Params.ContainsKey("SellerID"))
                    SellerID = Params["SellerID"] + "";

                Dictionary<string, string> Parameters = new Dictionary<string, string>();
                foreach (XmlNode n in nd.ChildNodes) {
                    Parameters.Add(n.Name, n.InnerText.Trim());
                }

                foreach (KeyValuePair<string, string> kvp in Parameters) {
                    switch (kvp.Value) {
                        case "string":
                        case "int":
                        case "double": {
                                if (Params.ContainsKey(kvp.Key))
                                    nd[(kvp.Key)].InnerText = Params[(kvp.Key)] + "";
                                else nd.RemoveChild(nd[(kvp.Key)]);
                                break;
                            }
                        case "boolean": {
                                if (Params.ContainsKey(kvp.Key))
                                    nd[(kvp.Key)].InnerText = (bool)Params[(kvp.Key)] ? "true" : "false";
                                else nd.RemoveChild(nd[(kvp.Key)]);
                                break;
                            }
                        #region specific
                        case "ItemConditionCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((ItemConditionCodeType)Params[kvp.Key]) != ItemConditionCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((ItemConditionCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "ExcludeFlagCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((ExcludeFlagCodeType)Params[kvp.Key]) != ExcludeFlagCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((ExcludeFlagCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "ItemLocationRegionCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((ItemLocationRegionCodeType)Params[kvp.Key]) != ItemLocationRegionCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((ItemLocationRegionCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "SimpleItemSortCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((SimpleItemSortCodeType)Params[kvp.Key]) != SimpleItemSortCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((SimpleItemSortCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "ItemTypeCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((ItemTypeCodeType)Params[kvp.Key]) != ItemTypeCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((ItemTypeCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "PaymentMethodSearchCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((PaymentMethodSearchCodeType)Params[kvp.Key]) != PaymentMethodSearchCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((PaymentMethodSearchCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "PreferredLocationCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((PreferredLocationCodeType)Params[kvp.Key]) != PreferredLocationCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((PreferredLocationCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "QuantityOperatorCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((QuantityOperatorCodeType)Params[kvp.Key]) != QuantityOperatorCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((QuantityOperatorCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "SearchFlagCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((SearchFlagCodeType)Params[kvp.Key]) != SearchFlagCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((SearchFlagCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "SellerBusinessCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((SellerBusinessCodeType)Params[kvp.Key]) != SellerBusinessCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((SellerBusinessCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "SortOrderCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((SortOrderCodeType)Params[kvp.Key]) != SortOrderCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((SortOrderCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        case "StoreSearchCodeType": {
                                if (Params.ContainsKey(kvp.Key))
                                    if (((StoreSearchCodeType)Params[kvp.Key]) != StoreSearchCodeType.NotSet)
                                        nd[kvp.Key].InnerText = ((StoreSearchCodeType)((int)Params[kvp.Key] - 1)).ToString();
                                    else nd.RemoveChild(nd[kvp.Key]);
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }
                        #endregion specific
                        case "dateTime": {
                                if (Params.ContainsKey(kvp.Key))
                                    if ((DateTime)Params[kvp.Key] == DateTime.MinValue)
                                        nd.RemoveChild(nd[kvp.Key]);
                                    else
                                        nd[kvp.Key].InnerText = ((DateTime)Params[kvp.Key]).ToString("o");
                                else nd.RemoveChild(nd[kvp.Key]);
                                break;
                            }

                        default:
                            nd.RemoveChild(nd[(kvp.Key)]);
                            break;
                    }
                }

                if (QueryKeywords == "" && CategoryID == "" && ProductID == "" && SellerID == "") throw new API.Exceptions.NoQueryParametersSetException();

                //Get XML into a string for use in encoding
                string xmlText = xmlDoc.InnerXml;


                //Put the data into a UTF8 encoded  byte array
                UTF8Encoding encoding = new UTF8Encoding();
                int dataLen = encoding.GetByteCount(xmlText);
                byte[] utf8Bytes = new byte[dataLen];
                Encoding.UTF8.GetBytes(xmlText, 0, xmlText.Length, utf8Bytes, 0);

                HttpWebRequest request = eBayRequest.SetupRequest("FindItemsAdvanced", utf8Bytes.Length, 623, 623, Global.Configuration.ShoppingAPIUrl);
                return new FindItemsAdvancedResponseType(eBayRequest.SendRequest(request, utf8Bytes));
            }
        }
    }
}
